package cn.zhuzicc.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.LocalDate;

/**
 * @author zx
 * @version 1.0
 * @className: Test09
 * @description: 通过反射动态创建对象
 * @date: 2021/4/28 10:22
 */
public class Test09 {
    public static void main(String[] args) throws Exception {
        Class c1 = Class.forName("cn.zhuzicc.reflect.User");

        // 1. 通过反射构造一个对象
        System.out.println("1. 通过反射构造一个对象");
        // 1.1 本质是调用了类的无参构造器
        User user = (User) c1.newInstance();
        System.out.println("1.1 本质是调用了类的无参构造器:\n" + user);
        // 1.2 通过类的有参构造器创建对象
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, Integer.class, LocalDate.class);
        user = (User) declaredConstructor.newInstance("张三", 21, LocalDate.of(2000, 3, 8));
        System.out.println("1.2 通过类的有参构造器创建对象:\n" + user);
        System.out.println("\n");


        // 2. 通过反射操作方法
        System.out.println("2. 通过反射操作方法");
        // 2.1 通过反射调用普通方法
        Method setName = c1.getDeclaredMethod("setName", String.class);
        user = (User) c1.newInstance();
        setName.invoke(user, "李四");
        System.out.println("2.1 通过反射调用普通方法:\n" + user.getName());
        // 2.1 通过反射调用私有方法
        System.out.println("2.1 通过反射调用私有方法:");
        Method thisSecret = c1.getDeclaredMethod("thisSecret", Boolean.class);
        thisSecret.setAccessible(true);
        thisSecret.invoke(user, true);
        System.out.println("\n");

        // 3. 通过反射操作属性
        System.out.println("3. 通过反射操作属性");
        Field name = c1.getDeclaredField("name");
        user = (User) c1.newInstance();
        name.setAccessible(true);
        name.set(user, "王五");
        System.out.println(user.getName());
    }
}
